package attack.nartan;

import java.awt.geom.Rectangle2D;

import org.newdawn.slick.Animation;
import org.newdawn.slick.GameContainer;
import org.newdawn.slick.Graphics;
import org.newdawn.slick.Image;
import org.newdawn.slick.SpriteSheet;
import org.newdawn.slick.geom.Point;
import org.newdawn.slick.geom.Rectangle;

import framework.AnimationManager;
import framework.BasicFighter;
import framework.Util;
import framework.attack.BasicAttack;
import framework.movements.LittleBackwardMovement;
import framework.movements.LinearMovement;

public class FireBall extends BasicAttack<BasicFighter> {

	protected Animation attackAnimation;

	protected Animation attackAnimationBackward;
	
	protected Animation attackJumpAnimation;

	protected Animation attackJumpAnimationBackward;

	protected Animation currentAttackAnimation;

	protected Animation ball;

	protected Animation ballBackward;

	protected Animation currentBall;
	
	protected Animation impact;

	protected SpriteSheet spriteSheet;
	
	private static final int BALL_SPEED = 1500;

	protected boolean completed;

	protected boolean hit;
	
	protected boolean interruptOnHit;
	
	protected boolean interruptOnBoundHit;

	public FireBall() {
		this(null);
	}

	public FireBall(BasicFighter attacker) {
		AnimationManager n = attacker.getAnimations();
		this.spriteSheet = n.getSpriteSheet();
		Image[] frames = new Image[2];
		frames[0] = this.spriteSheet.getSprite(0, 4);
		frames[1] = this.spriteSheet.getSprite(0, 4);
		frames[1].setAlpha(0.2f);
		this.ball = new Animation(frames, 50);
		this.ballBackward = Util.getFlippedAnimation(this.ball, true, false);
		this.impact = new Animation();
		this.impact.addFrame(spriteSheet.getSprite(1, 4), 300);
		frames = new Image[8];
		frames[0] = this.spriteSheet.getSprite(2, 2);
		frames[1] = this.spriteSheet.getSprite(3, 2);
		frames[2] = this.spriteSheet.getSprite(2, 2);
		frames[3] = this.spriteSheet.getSprite(3, 2);
		frames[4] = this.spriteSheet.getSprite(2, 2);
		frames[5] = this.spriteSheet.getSprite(3, 2);
		frames[6] = this.spriteSheet.getSprite(4, 2);
		frames[7] = this.spriteSheet.getSprite(4, 2);
		this.attackAnimation = new Animation(frames, 70);
		this.attackAnimation.setDuration(7, 100);
		this.attackAnimationBackward = Util.getFlippedAnimation(this.attackAnimation, true, false);
		this.attackAnimation.setLooping(false);
		this.attackAnimationBackward.setLooping(false);
		frames[0] = this.spriteSheet.getSprite(1, 3);
		frames[1] = this.spriteSheet.getSprite(2, 3);
		frames[2] = this.spriteSheet.getSprite(1, 3);
		frames[3] = this.spriteSheet.getSprite(2, 3);
		frames[4] = this.spriteSheet.getSprite(1, 3);
		frames[5] = this.spriteSheet.getSprite(2, 3);
		frames[6] = this.spriteSheet.getSprite(3, 3);
		frames[7] = this.spriteSheet.getSprite(3, 3);
		this.attackJumpAnimation = new Animation(frames, 70);
		this.attackJumpAnimation.setDuration(7, 100);
		this.attackJumpAnimationBackward = Util.getFlippedAnimation(this.attackJumpAnimation, true, false);
		this.attackJumpAnimation.setLooping(false);
		this.attackJumpAnimationBackward.setLooping(false);
		
		this.attacker = attacker;
		this.setWidth((int)getAttacker().getWidth());
		this.setHeight((int)getAttacker().getHeight());
		this.completed = false;
		this.interruptOnHit = true;
		this.interruptOnBoundHit = true;
	}

	@Override
	public void update(GameContainer gc, int delta) {
		super.update(gc, delta);
		boolean forward = this.currentBall == this.ball;
		if (completed) {
			setX(getX() + getStepXSpeed(delta));
		}
		if(completed && this.interruptOnBoundHit && (getX() + getWidth() < 0 && !forward || getX() > gc.getWidth()  && forward)) {
			super.interrupt();
		}
	}

	@Override
	public void draw(Graphics g) {
		completed = this.currentAttackAnimation.getFrame() >= this.currentAttackAnimation.getFrameCount() - 2;
		if(!this.currentAttackAnimation.isStopped()) {
			this.currentAttackAnimation.draw(getAttacker().getX(), getAttacker().getY(), getAttacker().getWidth(), getAttacker().getHeight());
		}
		if (this.currentAttackAnimation.getFrame() >= this.currentAttackAnimation.getFrameCount() - 2) {
			this.currentBall.draw(getX(), getY(), getAttacker().getWidth(), getAttacker().getHeight());
		}
	}

	@Override
	public Rectangle getHitBox() {
		int offset = getAttacker().getWidth() / 6;
		Rectangle hitBox;
		hitBox = null;
		if (completed) {
			if (this.currentBall == this.ball) {
				hitBox = new Rectangle((int)(getX() + 4.5 * offset), getY() + offset, offset, offset);	
			} else {
				hitBox = new Rectangle((int)(getX() + 0.5 * offset), getY() + offset, offset, offset);	
			}
		} 
		return hitBox;
	}

	@Override
	public void trigger() {
		//if (!getAttacker().isJumping()) {
			super.trigger();
			this.completed = false;
			this.hit = false;
			Rectangle hitbox = getAttacker().getHitBox();
			setXspeed(getAttacker().isForward() ? BALL_SPEED : -BALL_SPEED);
			setY((int)(getAttacker().getY()));
			if (getAttacker().isForward()) {
				this.currentAttackAnimation = getAttacker().isJumping() ? this.attackJumpAnimation : this.attackAnimation;
				this.currentBall = this.ball;
				setX((int)(hitbox.getX() - hitbox.getWidth() * 8));
			} else {
				this.currentAttackAnimation = getAttacker().isJumping() ? this.attackJumpAnimationBackward : this.attackAnimationBackward;
				this.currentBall = this.ballBackward;
				setX((int)(hitbox.getX() + hitbox.getWidth()));
			}
			this.currentAttackAnimation.restart();
			this.currentBall.restart();
			getAttacker().setYspeed(Math.abs(getAttacker().getYspeed()));
		//}
	}

	@Override
	public int getPower() {
		return 14;
	}

	@Override
	public int getDuration() {
		return 30000;
	}
	
	@Override
	public boolean collidesOnAttack() {
		return true;
	}

	@Override
	public void onHit(BasicFighter f, Rectangle2D collision) {
		super.onHit(f, collision);
		if (interruptOnHit) {
			LinearMovement m = new LinearMovement(f, new Point(f.getX() + 20 * getScale(), f.getY()));
			m.setDuration(200);
			LittleBackwardMovement move = new LittleBackwardMovement(f);
			f.move(move);
			
		    interrupt();
		}
	}

	@Override
	public boolean isBlocking() {
		return isActive() && this.currentAttackAnimation.getFrame() <= this.currentAttackAnimation.getFrameCount() - 2;
	}

	@Override
	public boolean isDrawingAttacker() {
		return isActive() && !this.currentAttackAnimation.isStopped();
	}

	@Override
	public boolean isInterruptable() {
		return isActive() && this.currentAttackAnimation.getFrame() <= this.currentAttackAnimation.getFrameCount() - 3;
	}
}
